package org.wk.account.service;

import com.alibaba.fastjson.JSONObject;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.wk.account.dao.SubAccountDao;
import org.wk.account.dao.bao.SubAccountBaoAdminUpdateBillDao;
import org.wk.account.dao.bao.SubAccountBaoDao;
import org.wk.account.dao.bao.SubAccountBaoSeqDao;
import org.wk.account.dao.bao.SubAccountBaoToZhongBillDao;
import org.wk.account.dao.zhong.SubAccountZhongDao;
import org.wk.account.dao.zhong.SubAccountZhongFromBaoBillDao;
import org.wk.account.dao.zhong.SubAccountZhongSeqDao;
import org.wk.account.domain.SubAccount;
import org.wk.account.domain.bao.SubAccountBao;
import org.wk.account.domain.bao.SubAccountBaoAdminUpdateBill;
import org.wk.account.domain.bao.SubAccountBaoSeq;
import org.wk.account.domain.bao.SubAccountBaoToZhongBill;
import org.wk.account.domain.zhong.SubAccountZhong;
import org.wk.account.domain.zhong.SubAccountZhongFromBaoBill;
import org.wk.account.domain.zhong.SubAccountZhongSeq;
import org.wk.account.enums.*;
import org.wk.core.common.view.ResponseVo;
import org.wk.core.db.tool.WebUtils;
import org.wk.core.web.exception.GeneralException;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 鲸宝服务实现类
 * @author TangShenShen
 * @date 2018/5/189:13
 */
@Service
public class SubAccountBaoServiceImpl implements SubAccountBaoService{

    @Autowired
    private SubAccountDao subAccountDao;
    @Autowired
    private SubAccountBaoDao subAccountBaoDao;
    @Autowired
    private SubAccountZhongDao subAccountZhongDao;
    @Autowired
    private SubAccountBaoSeqDao subAccountBaoSeqDao;
    @Autowired
    private SubAccountZhongSeqDao subAccountZhongSeqDao;
    @Autowired
    private SubAccountBaoToZhongBillDao subAccountBaoToZhongBillDao;
    @Autowired
    private SubAccountZhongFromBaoBillDao subAccountZhongFromBaoBillDao;
    @Autowired
    private SubAccountBaoAdminUpdateBillDao subAccountBaoAdminUpdateBillDao;

    /**
     * @Description 鲸宝兑换鲸种
     * @Param [targetAccountType, jsonObject]
     * @author ZhaoPing'an
     * @Date 2018/5/18 11:30
     */
    @Override
    public ResponseVo jingbaoExchangeOthers(String targetAccountType, JSONObject jsonObject) {
        String userId = WebUtils.getUser().getId();
        // 兑换规则100:1
        int exchange_rule = 100;
        int quantity = jsonObject.getIntValue("quantity");
        if (quantity%100!=0 || quantity < 100){
            return new ResponseVo(ResponseCode.COMPLETE_DATA);
        }
        SubAccountBao subAccountBao = subAccountBaoDao.findByUserId(userId);
        BigDecimal preAmount = subAccountBao.getAmount();
        // 鲸宝总数与当前兑换数量校验
        if (preAmount.doubleValue()<(double)quantity){
            return new ResponseVo(ResponseCode.AMOUNT_DATA_ERROR);
        }
        // 鲸宝操作
        SubAccountBaoToZhongBill subAccountBaoToZhongBill = new SubAccountBaoToZhongBill();
        subAccountBaoToZhongBill.setAmount(new BigDecimal(quantity));
        subAccountBaoToZhongBill.setUserId(userId);
        subAccountBaoToZhongBillDao.save(subAccountBaoToZhongBill);
        subAccountBao.setUserId(userId);
        subAccountBao.setAmount(preAmount.subtract(new BigDecimal(quantity)));
        subAccountBaoDao.saveOrUpdate(subAccountBao);
        SubAccountBaoSeq SubAccountBaoSeq = new SubAccountBaoSeq();
        SubAccountBaoSeq.setUserId(userId);
        SubAccountBaoSeq.setSeqFlagCode(SeqFlag.EXPEND.getCode());
        SubAccountBaoSeq.setSeqFlagName(SeqFlag.EXPEND.getName());
        SubAccountBaoSeq.setChangeTypeCode(BaoChangeType.TO_ZHONG.getCode());
        SubAccountBaoSeq.setChangeTypeName(BaoChangeType.TO_ZHONG.getName());
        SubAccountBaoSeq.setPreAmount(preAmount);
        SubAccountBaoSeq.setAmount(subAccountBao.getAmount());
        SubAccountBaoSeq.setChangeAmount(new BigDecimal(quantity));
        subAccountBaoSeqDao.save(SubAccountBaoSeq);
        SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_BAO.getCode());
        subAccount.setAmount(preAmount.subtract(new BigDecimal(quantity)));
        subAccountDao.update(subAccount);

        // 鲸种操作
        SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
        int nowAmount = subAccountZhong.getAmount();
        int exchangeAmount = quantity/exchange_rule;
        int exchangeAfterAmount = nowAmount+exchangeAmount;
        subAccountZhong.setUserId(userId);
        subAccountZhong.setAmount(exchangeAfterAmount);
        subAccountZhongDao.saveOrUpdate(subAccountZhong);
        SubAccountZhongFromBaoBill subAccountZhongFromBaoBill = new SubAccountZhongFromBaoBill();
        subAccountZhongFromBaoBill.setAmount(exchangeAmount);
        subAccountZhongFromBaoBill.setUserId(userId);
        subAccountZhongFromBaoBillDao.save(subAccountZhongFromBaoBill);
        SubAccountZhongSeq subAccountZhongSeq = new SubAccountZhongSeq();
        subAccountZhongSeq.setUserId(userId);
        subAccountZhongSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
        subAccountZhongSeq.setSeqFlagName(SeqFlag.INCOME.getName());
        subAccountZhongSeq.setChangeTypeCode(ZhongChangeType.FROM_BAO.getCode());
        subAccountZhongSeq.setChangeTypeName(ZhongChangeType.FROM_BAO.getName());
        subAccountZhongSeq.setPreAmount(nowAmount);
        subAccountZhongSeq.setAmount(exchangeAfterAmount);
        subAccountZhongSeq.setChangeAmount(exchangeAmount);
        subAccountZhongSeqDao.save(subAccountZhongSeq);
        subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId,AccountType.JING_ZHONG.getCode());
        subAccount.setAmount(new BigDecimal(exchangeAfterAmount));
        subAccountDao.update(subAccount);
        JSONObject json = new JSONObject();
        json.put("date",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
        return ResponseVo.success().setData(json);

    }


    @Override
    public Page<SubAccountBaoSeq> findSeqByCriteria(Integer page, Integer size, SubAccountBaoSeq subAccountBaoSeq) {
        Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
        Page<SubAccountBaoSeq> baoSeqPage = subAccountBaoSeqDao.findAll(new Specification<SubAccountBaoSeq>() {
            @Override
            public Predicate toPredicate(Root<SubAccountBaoSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                if(null!=subAccountBaoSeq.getUserId()&&!"".equals(subAccountBaoSeq.getUserId())){
                    list.add(criteriaBuilder.equal(root.get("userId").as(String.class), subAccountBaoSeq.getUserId()));
                }
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            }
        }, PageRequest.of(page,size,sort));
        return baoSeqPage;
    }

    /*
     * @description PC修改鲸宝数量
     * @param
     * @author ZhaoPing'an
     * @date 2018/8/13 15:15
     */
    @Override
    public void updateBaoAccount(BigDecimal bao,String userId) {
        SubAccountBao subAccountBao = subAccountBaoDao.findByUserId(userId);
        SubAccountBaoSeq subAccountBaoSeq = new SubAccountBaoSeq();
        BigDecimal amount = subAccountBao.getAmount();
        BigDecimal changeAmount = new BigDecimal(0);
        int num = bao.compareTo(amount);
        if (num < 0){
            changeAmount = amount.subtract(bao);
            subAccountBaoSeq.setSeqFlagCode(SeqFlag.EXPEND.getCode());
            subAccountBaoSeq.setSeqFlagName(SeqFlag.EXPEND.getName());
        }
        if (num > 0){
            changeAmount = bao.subtract(amount);
            subAccountBaoSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
            subAccountBaoSeq.setSeqFlagName(SeqFlag.INCOME.getName());
        }
        if (num!=0 && bao.compareTo(new BigDecimal(0))>=0){
            SubAccountBaoAdminUpdateBill adminUpdateBill = new SubAccountBaoAdminUpdateBill();
            adminUpdateBill.setAmount(changeAmount);
            adminUpdateBill.setUserId(userId);
            subAccountBaoAdminUpdateBillDao.save(adminUpdateBill);
            subAccountBao.setAmount(bao);
            subAccountBao.setUserId(userId);
            subAccountBaoDao.saveOrUpdate(subAccountBao);
            subAccountBaoSeq.setUserId(userId);
            subAccountBaoSeq.setChangeTypeCode(BaoChangeType.ADMIN_UPDATE.getCode());
            subAccountBaoSeq.setChangeTypeName(BaoChangeType.ADMIN_UPDATE.getName());
            subAccountBaoSeq.setPreAmount(amount);
            subAccountBaoSeq.setAmount(bao);
            subAccountBaoSeq.setChangeAmount(changeAmount);
            subAccountBaoSeqDao.save(subAccountBaoSeq);
            SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_BAO.getCode());
            subAccount.setAmount(bao);
            subAccountDao.update(subAccount);
        }
    }

    @Override
    public Page<SubAccountBaoSeq> findSeqByUserIds(int pageNum, int pageSize, List<String> userIds) {
        Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
        Page<SubAccountBaoSeq> baoSeqPage = subAccountBaoSeqDao.findAll(new Specification<SubAccountBaoSeq>() {
            @Override
            public Predicate toPredicate(Root<SubAccountBaoSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                if(!userIds.isEmpty()){
                    CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("userId"));
                    for (String userId:userIds){
                        in.value(userId);
                    }
                    list.add(in);
                }
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            }
        }, PageRequest.of(pageNum,pageSize,sort));
        return baoSeqPage;
    }

}
